#include <iostream>
#include <memory>
using namespace std;
// 装饰器模式

//抽象类作为接口
class Component
{
public:
    Component()
    {
        cout << "Component()" << endl;
    }
    virtual ~Component()
    {
        cout << "~Component()" << endl;
    }
    virtual void operation() = 0;
};
class ConcreateComponent : public Component
{
public:
    ConcreateComponent()
    {
        cout << "ConcreateComponent()" << endl;
    }
    virtual void operation()
    {
        cout << "具体对象的操作" << endl;
    }
    ~ConcreateComponent()
    {
        cout << "~ConcreateComponent" << endl;
    }
};
// 装饰器
class Decorator : public Component
{
public:
    Decorator()
    {
        cout << " Decorator()" << endl;
    }

    void setComponent(Component *pComponent)
    {
        _pComponent = pComponent;
    }
    virtual void operation()
    {
        if (_pComponent != nullptr)
        {
            _pComponent->operation();
            // 基类的指针调用虚函数，运行时多态。
        }
    }
    ~Decorator()
    {
        cout << "~Decorator()" << endl;
    }

private:
    Component *_pComponent;
};
// 具体的装饰器A
class ConcreateDecoratorA : public Decorator
{
public:
    ConcreateDecoratorA()
    {
        cout << "ConcreateDecoratorA()" << endl;
    }
    virtual void operation()
    {
        // 调用父类的operation()
        Decorator::operation();
        addBehavior();
    }
    void addBehavior()
    {
        cout << "为具体构件A扩展的操作" << endl;
    }
    ~ConcreateDecoratorA()
    {
        cout << "~ConcreateDecoratorA()" << endl;
    }
};
// 具体的装饰器B
class ConcreateDecoratorB : public Decorator
{
public:
    ConcreateDecoratorB()
    {
        cout << "ConcreateDecoratorB()" << endl;
    }
    virtual void operation()
    {
        // 调用父类的operation()
        Decorator::operation();
        addBehavior();
    }
    void addBehavior()
    {
        cout << "为具体构件B扩展的操作" << endl;
    }
    ~ConcreateDecoratorB()
    {
        cout << "~ConcreateDecoratorB()" << endl;
    }
};
int main()
{
    //1.创建基础组件
    unique_ptr<Component> pcom(new ConcreateComponent());
    unique_ptr<Decorator> pdA(new ConcreateDecoratorA());
    unique_ptr<Decorator> pdB(new ConcreateDecoratorB());
    //Component* pcom -> ConcreateComponent
    //Decorator * pdA -> ConcreateDecoratorA
    //Decorator * pdB -> ConcreateDecoratorB
    pdA->setComponent(pcom.get());//pdA 装饰 pcom
    pdB->setComponent(pdA.get());//pdB 装饰 pdA
    pdB->operation();

    return 0;
}
